package com.fastwire.carriere.discovery;

import java.net.MalformedURLException;
import java.util.List;
import java.util.concurrent.Callable;

import javax.xml.ws.Holder;

import org.tmforum.mtop.fmw.xsd.gen.v1.AliasNameListType;
import org.tmforum.mtop.fmw.xsd.hdr.v1.CommunicationPatternType;
import org.tmforum.mtop.fmw.xsd.hdr.v1.CommunicationStyleType;
import org.tmforum.mtop.fmw.xsd.hdr.v1.Header;
import org.tmforum.mtop.fmw.xsd.nam.v1.NamingAttributeType;
import org.tmforum.mtop.fmw.xsd.nam.v1.RelativeDistinguishNameType;
import org.tmforum.mtop.mri.wsdl.mer.v1_0.GetAllManagedElementsException;
import org.tmforum.mtop.mri.wsdl.mer.v1_0.ManagedElementRetrievalHttp;
import org.tmforum.mtop.mri.wsdl.mer.v1_0.ManagedElementRetrievalRPC;
import org.tmforum.mtop.mri.xsd.mer.v1.GetAllManagedElementsRequest;
import org.tmforum.mtop.mri.xsd.mer.v1.MultipleMeObjectsResponseType;
import org.tmforum.mtop.nrf.xsd.me.v1.ManagedElementType;

import com.fastwire.carriere.callable.ConcurrentDiscoveryInteraction;
import com.fastwire.carriere.common.constant.AppConstants;
import com.fastwire.carriere.common.exception.U2000ProcessException;
import com.fastwire.carriere.common.util.CommonLogger;
import com.fastwire.carriere.huawei.mtopsi.ra.HuaweiMTOSIConnection;
import com.fastwire.carriere.inventory.entity.NetworkElement;
import com.google.common.collect.Lists;

public class NetworkEntityConcurrentDiscovery extends NetworkEntityDiscovery {

	List<Callable<List>> callables = Lists.newArrayList();
	
	public List<Callable<List>> getCallables() {
		return callables;
	}

	public void doNEDiscovery(String type) throws U2000ProcessException {

		GetAllManagedElementsRequest request = new GetAllManagedElementsRequest();
		Holder<Header> headerHolder = new Holder<Header>();
		Header header = new Header();

		headerHolder.value = header;
		header.setSecurity(HuaweiMTOSIConnection.getSecurity());
		header.setCommunicationPattern(CommunicationPatternType.MULTIPLE_BATCH_RESPONSE);
		header.setCommunicationStyle(CommunicationStyleType.RPC);

		long requestedBatchSize = Long.parseLong(HuaweiMTOSIConnection
				.getNeFetchSize());
		header.setRequestedBatchSize(requestedBatchSize);
		header.setBatchSequenceNumber((long) 1);

		NamingAttributeType mdType = new NamingAttributeType();
		List<RelativeDistinguishNameType> ednList = mdType.getRdn();
		RelativeDistinguishNameType mdRdn = new RelativeDistinguishNameType();
		mdRdn.setType("MD");
		mdRdn.setValue("Huawei/U2000");
		ednList.add(mdRdn);
		request.setMdOrMlsnRef(mdType);

		Holder<MultipleMeObjectsResponseType> responseHolder = new Holder<MultipleMeObjectsResponseType>();

		try {

			ManagedElementRetrievalHttp service = new ManagedElementRetrievalHttp(
					HuaweiMTOSIConnection.getWebServiceURL(AppConstants.ME_NRF));

			ManagedElementRetrievalRPC port = service
					.getManagedElementRetrievalRPC();

			do {
				port.getAllManagedElements(headerHolder, request,
						responseHolder);

				List<ManagedElementType> meList = responseHolder.value
						.getMeList().getMe();

				CommonLogger.info(this, "batch ME discovered:"
						+ responseHolder.value.getMeList().getMe().size());

				CommonLogger.info(
						this,
						"batch Header URI"
								+ headerHolder.value.getIteratorReferenceURI());

				List<NetworkElement> neList = Lists.newArrayList();
				for (ManagedElementType managedElementType : meList) {
					NetworkElement networkElement = new NetworkElement();
					networkElement.setNeType(managedElementType
							.getProductName());
					networkElement.setName(managedElementType.getName()
							.getRdn().get(1).getValue());
					CommonLogger
							.info(this, "ne is:" + networkElement.getName());
					networkElement.setEmsNativeName(managedElementType
							.getProductName());
					networkElement.setIpAddress(managedElementType
							.getIpaddress());
					networkElement.setSoftwareVersion(managedElementType
							.getSoftwareVersion());

					AliasNameListType aliasNameListType = managedElementType
							.getAliasNameList();
					List<AliasNameListType.Alias> aliasNameListTypes = aliasNameListType
							.getAlias();
					networkElement.setEmsNativeName(aliasNameListTypes.get(0)
							.getAliasValue());
					neList.add(networkElement);
				}

				callables.add(new ConcurrentDiscoveryInteraction(neList, type));
			} while (headerHolder.value.isBatchSequenceEndOfReply()
					.booleanValue() == false);

		} catch (GetAllManagedElementsException e) {
			e.printStackTrace();

			CommonLogger.error(this, e.getFaultInfo().toString());

			throw new U2000ProcessException(e.getMessage());
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new U2000ProcessException(
					"MalformedURLException: siacoverAlNE()" + e.getMessage());
		}

	}

	public List<Callable<List>> getCallables(List<NetworkElement> neList,
			String type) {
		int requestedBatchSize = Integer.parseInt(HuaweiMTOSIConnection
				.getNeFetchSize());

		int totalNEs = neList.size();
		int fromIndex = 0;

		while (totalNEs > 0) {
			int fetchSize = Math.min(totalNEs, requestedBatchSize);
			CommonLogger.info(this, "New callable is created: from "
					+ fromIndex + ", size " + fetchSize);
			callables.add(new ConcurrentDiscoveryInteraction(neList.subList(
					fromIndex, fromIndex + fetchSize), type));
			totalNEs -= requestedBatchSize;
			fromIndex += requestedBatchSize;
		}

		return callables;

	}

}
